package com.specter.serv.controller;

import static com.specter.sure.core.AuthConsts.KEY_SESSION_FROM;
import static com.specter.sure.core.AuthConsts.TOKEN_FROM_COOKIE;
import static com.specter.sure.core.AuthConsts.TOKEN_FROM_HEADER;
import static com.specter.sure.core.AuthConsts.URL_SAUTH_AUTHORIZE;

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import com.specter.mvc.model.Response;
import com.specter.sure.core.AuthConfig;
import com.specter.sure.core.StokenizorProvider;
import com.specter.utils.CookieUtils;
import com.specter.utils.StringUtils;
import com.specter.utils.URLUtils;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;

/**
 * 
 * 登录认证服务(Server)
 * 
 * @author Liang.Wang
 * @since 2025-04-02 12:12:12
 *
 */
@Slf4j
@Controller
@RequestMapping({ "/serv/auth", "/sure/sauth" })
public class AuthServerController {

	private @Autowired AuthConfig PROP;
	private @Autowired StokenizorProvider storage;

	/**
	 * 根据登录用户信息生成Code并重定向至客户端
	 * 
	 * @param request 单点登录请求
	 * @return 重定向至客户端或服务端登录
	 */
	@RequestMapping("/authorize")
	public HttpEntity<?> authorize(HttpServletRequest request) {
		if (request.getContentType() == null || request.getContentType().contains(MediaType.APPLICATION_FORM_URLENCODED_VALUE)) {
			return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(Response.failure("invalid_request"));
		}

		String jwt = CookieUtils.getAESCookie(request, TOKEN_FROM_COOKIE);
		if (StringUtils.isBlank(jwt)) {
			String auth = request.getHeader(TOKEN_FROM_HEADER);
			jwt = StringUtils.isBlank(auth) ? null : auth.substring(7);// "Authorization":"Bearer TOKEN"
		}

		String callback = request.getParameter("redirect_uri");
		ResponseEntity<String> res = null;
		if (storage.tokenValidate(jwt) == null) {
			String login = URLUtils.constructRedirectURL(request, PROP.AUTHORIZE_URL_LOGIN);
			System.out.println("2.2/sso failure then to sso login: " + login);// 验证不通过

			// 方便登录以后跳转
			request.getSession().setAttribute(KEY_SESSION_FROM, URL_SAUTH_AUTHORIZE + "?redirect_uri=" + callback);
			if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
				// AJAX请求只能一次redirect(302),故设置为405
				res = ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED)
						.header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_LOCATION)
						.header(HttpHeaders.CONTENT_LOCATION, login).build();// 重定向地址
			} else {
				// 普通请求直接redirect(302)到登录页面
				res = ResponseEntity.status(HttpStatus.FOUND).header(HttpHeaders.LOCATION, login).build();
			}
		} else {
			String authorizationCode = storage.ticketCreate(jwt);
			callback = callback + (callback.contains("?") ? "&" : "?") + "code=" + authorizationCode;
			System.out.println("2.1/sso success then callback client: " + callback);

			if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
				// AJAX请求只能一次redirect(302),故直接执行结果
				res = (new RestTemplate()).getForEntity(callback, String.class);// callback中如有重定向 将自动执行
			} else {
				// 普通请求直接redirect(302)到callback
				res = ResponseEntity.status(HttpStatus.FOUND).header(HttpHeaders.LOCATION, callback).build();
			}
		}
		return res;
	}

	/**
	 * 为客户端提供按照Code获取用户信息
	 * 
	 * @param request 用户Code
	 * @return 登录信息
	 */
	@ResponseBody
	@RequestMapping("/userbycode")
	public ResponseEntity<?> userbycode(HttpServletRequest request) {
		String authorizationCode = request.getParameter("code");
		String jwt = storage.ticketValidate(authorizationCode);
		Map<String, String> map = storage.tokenValidate(jwt);
		if (map == null) {
			return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(Response.failure("invalid_token"));
		}
		return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(Response.success().data(map.get("payload")));
	}

	/**
	 * 为客户端提供按照token获取用户信息
	 * 
	 * @param request 用户Token
	 * @return 登录信息
	 */
	@ResponseBody
	@RequestMapping("/userbytoken")
	public ResponseEntity<?> userbytoken(HttpServletRequest request) {
		Map<String, String> map = storage.tokenValidate(request.getParameter("stoken"));
		if (map == null) {
			return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(Response.failure("invalid_token"));
		}
		return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(Response.success().data(map.get("payload")));
	}

}
